<template>
  <div class="table_div">
    <table
      id="tableId"
      class="table_style"
      @focusin="gridOnFocus"
      @dblclick="gridOnBlur"
      @keydown="gridOnKeyDown"
      @keyup="gridOnKeyUp"
    >
      <tr class="tr_th">
        <th v-for="(item, index) in TableConfig.columnData" :key="index" v-if="item.isShow">
          <p v-if="item.isRequired"><span class="star">*</span>{{ item.name }}</p>
          <p v-else>{{ item.name }}</p>
        </th>
      </tr>
      <tr
        v-for="(item, index) in TableConfig.tableData"
        :key="index"
        :class="index == showbackGroundStyle ? 'active_backGround' : ''"
        @focusin="showbackGroundStyle = index"
        @mousemove="showbackGroundStyle = index"
        @mouseleave="showbackGroundStyle = -1"
      >
        <td class="first_td" @mousemove="showBtn = index" @mouseleave="showBtn = -1">
          <div v-if="showBtn == index" class="first_td_button">
            <p @click="addRow($event, index, TableConfig.tableData)"><span>+</span></p>
            <p @click="deleteRow(index, TableConfig.tableData)"><span>-</span></p>
          </div>
          <p class="first_td_p" v-else>{{ index + 1 }}</p>
        </td>
        <td v-for="(v, k) in item" :key="k" v-if="TableConfig.columnData[k].isShow">
          <input v-if="k.indexOf('Date') != -1" type="date" v-model="item[k]" style="width: 130px" />
          <input v-else type="text" v-model="item[k]" />
        </td>
      </tr>
      <tr class="last_tr">
        <td v-for="(item, index) in TableConfig.columnData" :key="index" v-if="item.isShow">
          <p v-if="item.key == 'seq'">合计</p>
          <p v-if="item.key == 'productCode'">共{{ TableConfig.tableData.length }}条明细</p>
          <p v-if="item.isSum">
            {{
              item.key == 'number'
                ? cnumberSum
                : item.key == 'money'
                ? cmoneySum
                : item.key == 'arrivalQty'
                ? carrivalQtySum
                : item.key == 'unArrivalQty'
                ? cunArrivalQtySum
                : ''
            }}
          </p>
        </td>
      </tr>
    </table>
    <div
      class="tip_box"
      :style="{
        top: tipList.top + 'px',
        left: tipList.left + 'px',
        display: tipList.displaySta,
      }"
    >
      <table id="tipTable">
        <tr
          @mousemove="activeMark(index)"
          @click="selectMark"
          v-for="(item, index) in tipList.listData"
          :key="index"
          :class="index == tipList.mark ? 'active_mark' : ''"
        >
          <td v-for="(v, k) in item" :key="k">{{ v }}</td>
        </tr>
      </table>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    TableConfig: Object,
    // addRow: Function,
    // deleteRow: Function,
  },
  data() {
    return {
      testmodel: 30,
      showBtn: -1, // 是否显示添加删除按钮
      showbackGroundStyle: -1,
      sum: {
        numberSum: 0,
        moneySum: 0,
        arrivalQtySum: 0,
        unArrivalQtySum: 0,
      },
      tableWidth: 1000,

      // 提示框数据
      tipList: {
        top: 0,
        left: 0,
        displaySta: 'none', //是否显示提示框
        listData: [], //提示框内数据集合
        mark: -1, //激活当前选中行状态
      },
      myRowIndex: 0, // 表格中当前选中第几行的下标
      selectListData: {}, // 提示框中当前选中第几行的数据
      eventTd: '',
    }
  },
  created() {
    this.handleTableData()
  },
  mounted() {
    let tableBox = document.getElementById('tableId')
    this.tableWidth = tableBox.scrollWidth
  },
  computed: {
    cnumberSum() {
      let sum = 0
      this.TableConfig.tableData.forEach((item) => {
        sum += Number(item.number)
      })
      sum = sum.toFixed(2)
      return sum
    },
    cmoneySum() {
      let sum = 0
      this.TableConfig.tableData.forEach((item) => {
        sum += Number(item.money)
      })
      sum = sum.toFixed(2)
      return sum
    },
    carrivalQtySum() {
      let sum = 0
      this.TableConfig.tableData.forEach((item) => {
        sum += Number(item.arrivalQty)
      })
      sum = sum.toFixed(2)
      return sum
    },
    cunArrivalQtySum() {
      let sum = 0
      this.TableConfig.tableData.forEach((item) => {
        sum += Number(item.unArrivalQty)
      })
      sum = sum.toFixed(2)
      return sum
    },
  },
  methods: {
    // 表格聚焦时触发触发
    gridOnFocus(event) {
      let obj = event.target
      obj.select()
      // 判断当前触发的节点为输入框
      if (obj.nodeName == 'INPUT') {
        let td = this.findtd(obj)
        let tr = td.parentNode //当前td所在的tr
        let myindex = Array.prototype.indexOf.call(tr.children, td) // 判断当前所触发元素在当前行的第几列
        // 全局使用判断当前所触发的输入框位于表格的第几行
        this.myRowIndex = Array.prototype.indexOf.call(tr.parentNode.children, tr) - 1
        // 判断是否是需要弹出提示框的列
        if (myindex == 1) {
          // 弹出提示框并改变提示框位置
          console.log(td.offsetParent.offsetTop, td.offsetParent.offsetBottom)
          this.tipList.top = td.offsetParent.offsetTop + 30
          this.tipList.left = obj.offsetParent.offsetLeft
          this.tipList.displaySta = 'block'
          // 判断当前输入框的内的值是否与提示框内的值匹配，如果匹配提示框改为选中状态
          this.OnFocusHandle(obj)
        } else {
          this.tipList.displaySta = 'none'
        }
      }
    },
    // 聚焦时处理
    OnFocusHandle(obj) {
      for (let i = 0; i < this.tipList.listData.length; i++) {
        // 判断当前输入框的值与提示框的哪一行值匹配
        if (this.tipList.listData[i].productCode == obj.value) {
          this.tipList.mark = i // 改变提示框选中行下标
          this.selectListData = this.tipList.listData[this.tipList.mark]
          let cptbl = document.getElementById('tipTable')
          let ptr = cptbl.rows[this.tipList.mark]
          // 避免第一次触发出现问题 添加定时器
          setTimeout(() => {
            // 将当前选中行滚动到浏览器可视区域
            ptr.scrollIntoViewIfNeeded()
          }, 0)
          return
        } else {
          this.tipList.mark = -1
        }
      }
    },
    // 失焦时触发
    gridOnBlur() {
      this.tipList.displaySta = 'none'
    },

    // 键盘按下时触发
    gridOnKeyDown(event) {
      let obj = event.target // 当前触发的input
      let td = this.findtd(obj) // 当前input所在的td
      let tdRight = td.nextElementSibling // 当前td的右边
      let tdLeft = td.previousElementSibling // 当前td的左边
      let tr = td.parentNode // 当前td所在的tr
      let trUp = tr.previousElementSibling // 当前tr的上一行
      let trDown = tr.nextElementSibling // 当前tr的下一行
      let myindex = Array.prototype.indexOf.call(tr.children, td) // 判断当前所触发元素在当前行的第几列
      // 判断当前所触发的节点 位于表格的第几行
      this.getTrIndex(tr)
      // 如果触发的是输入框 且 触发的是第一列数据时
      if (obj.nodeName == 'INPUT' && myindex == 1) {
        // 如果当前键盘事件为向下 且 提示框为显示状态
        if (event.key == 'ArrowDown' && this.tipList.displaySta == 'block') {
          this.handleTipBox('ArrowDown')
          // 如果当前键盘事件为向上 且 提示框为显示状态
        } else if (event.key == 'ArrowUp' && this.tipList.displaySta == 'block') {
          this.handleTipBox('ArrowUp')
          // 如果当前键盘事件为回车 且 提示框为显示状态 提示框内也有选择数据时
        } else if (event.key == 'Enter' && this.tipList.displaySta == 'block' && this.tipList.mark != -1) {
          this.handleTipBoxEnter(tdRight, 'Enter')
          // 如果当前键盘事件为回车 且 提示框为显示状态
        } else if (event.key == 'ArrowRight' || (event.key == 'Enter' && this.tipList.displaySta == 'block')) {
          this.handleTipBoxEnter(tdRight)
        }
      } else {
        // 当触发的不是第一列节点时 隐藏提示框
        this.tipList.displaySta = 'none'
        // 判断键盘事件 选择相应的节点
        this.nodeSelect(tdRight, tdLeft, tr, trUp, trDown, myindex)
      }
    },
    // 找到当前tr的下标
    getTrIndex(tr) {
      let tableBox = document.getElementById('tableId')
      let allTr = tableBox.getElementsByTagName('tr')
      if (tr.nodeName.toLowerCase() == 'tr') {
        for (var i = 0; i < allTr.length; i++) {
          if (allTr[i] === tr) {
            if (i >= 0) {
              this.myRowIndex = i - 1
            }
          }
        }
      }
    },
    // 处理提示框的数据显示 及 替换表格内当前选中的数据
    handleTipBox(downState) {
      if (downState == 'ArrowDown' && this.tipList.mark != this.tipList.listData.length - 1) {
        // 如果按键向下 且 当前选中数据为最后一个时 当前选中数据+1
        this.tipList.mark++
      } else if (downState == 'ArrowUp' && this.tipList.mark != 0 && this.tipList.mark != -1) {
        // 如果按键向上 且 当前选中数据不是第一个也不是未选则时 当前选中数据-1
        this.tipList.mark--
      } else if (downState == 'ArrowUp' && this.tipList.mark == -1) {
        // 如果按键向上 且 当前选中数据是未选则时 当前选中数据为提示框的最后一条数据
        this.tipList.mark = this.tipList.listData.length - 1
      }
      // 获取提示框table 得到当前选中行自动滚动到可视区域
      let cptbl = document.getElementById('tipTable')
      let ptr = cptbl.rows[this.tipList.mark]
      this.selectListData = this.tipList.listData[this.tipList.mark]
      ptr.scrollIntoViewIfNeeded()
      for (const key in this.TableConfig.tableData[this.myRowIndex]) {
        // 替换当前选中数据
        this.TableConfig.tableData[this.myRowIndex][key] = this.selectListData[key]
      }
    },
    // 处理提示框按下回车后操作
    handleTipBoxEnter(tdRight, downState) {
      this.tipList.displaySta = 'none' // 隐藏提示框
      this.selectInput(tdRight) // 选中当前输入框的下一个
      if (downState == 'Enter') {
        for (const key in this.TableConfig.tableData[this.myRowIndex]) {
          // 替换当前选中数据
          this.TableConfig.tableData[this.myRowIndex][key] = this.selectListData[key]
        }
      }
    },
    // 判断键盘事件 选择相应的节点
    nodeSelect(tdRight, tdLeft, tr, trUp, trDown, myindex) {
      if (event.key == 'Enter') {
        if (myindex == tr.children.length - 1) {
          if (this.myRowIndex != this.TableConfig.tableData.length - 1) {
            this.selectInput(trDown.children[1])
          }
        } else {
          if (myindex == 9) {
            let dateInput = this.findinput(tdRight)
            // this.findinput(tdRight).onclick();
          }
          this.selectInput(tdRight)
        }
      } else if (event.key == 'ArrowUp') {
        if (this.myRowIndex != 0) {
          this.selectInput(trUp.children[myindex])
        }
      } else if (event.key == 'ArrowRight') {
        if (myindex == tr.children.length - 1) {
          this.selectInput(trDown.children[1])
        } else {
          this.selectInput(tdRight)
        }
      } else if (event.key == 'ArrowDown') {
        if (this.myRowIndex != this.TableConfig.tableData.length - 1) {
          this.selectInput(trDown.children[myindex])
        }
      } else if (event.key == 'ArrowLeft') {
        this.selectInput(tdLeft)
      }
    },
    // 选中当前输入框
    selectInput(selectNode) {
      let nextInput = this.findinput(selectNode)
      event.preventDefault() // 阻止默认行为
      nextInput.select()
      nextInput.scrollIntoViewIfNeeded()
    },
    // 遍历找到td
    findtd(elm) {
      if (elm && elm.parentNode) {
        if (elm.parentNode.nodeName == 'TD') {
          return elm.parentNode
        } else {
          this.findtd(elm.parentNode)
        }
      }
    },
    // 遍历找到input
    findinput(elm) {
      if (elm && elm.children[0]) {
        if (elm.children[0].nodeName == 'INPUT') {
          return elm.children[0]
        } else {
          this.findinput(elm.children[0])
        }
      }
    },
    // 键盘抬起时触发
    gridOnKeyUp(event) {
      event.preventDefault() // 阻止默认行为
      let obj = event.target // 当前触发的input
      let td = this.findtd(obj) // 当前input所在的td
      let tr = td.parentNode // 当前td所在的tr
      let myindex = Array.prototype.indexOf.call(tr.children, td) // 判断当前所触发元素在当前行的第几列
      // 判断当前所触发的节点 位于表格的第几行
      this.getTrIndex(tr)
      // 如果触发的是输入框 且 触发的是第一列数据时
      if (obj.nodeName == 'INPUT' && myindex == 1) {
        if (event.key == 'ArrowDown' || event.key == 'ArrowUp' || event.key == 'Backspace' || event.key == 'Delete') {
          event.preventDefault()
        } else {
          //寻找对应的匹配索引
          let oldvalue = obj.value
          // 输入框非空判断
          if (obj.value != '') {
            let pipei_index = this.findProductIndex(obj.value)
            // 修改提示框选中行
            this.tipList.mark = pipei_index
            //如果有匹配的行
            if (pipei_index >= 0) {
              // 获取提示框当前选中行数据
              this.selectListData = this.tipList.listData[pipei_index]
              // // 获取提示框当前选中行数据
              // let pipei_product = this.tipList.listData[pipei_index];
              // 得到与输入框相匹配的值
              let inputValue = this.findProduct(obj.value, this.selectListData)
              // 商品编码赋值
              if (inputValue != '') {
                let productcd = inputValue
                // if(obj.productCode != productcd){
                obj.value = productcd
                obj.select()
                // }
                obj.selectionStart = oldvalue.length
              }

              // 其他部分赋值(未使用，存在改变光标问题)
              // this.selectListData = this.tipList.listData[pipei_index];
              // for (const key in this.TableConfig.tableData[this.myRowIndex]){
              //   // 替换当前选中数据
              //   if (key=="productCode") {
              //   } else {
              //     this.TableConfig.tableData[this.myRowIndex][key] = this.selectListData[key];
              //   }
              // }
            }
          }
        }
      }
    },
    // 找到输入框的值在提示框的哪一行
    findProductIndex(inputvalue) {
      let length = this.tipList.listData.length
      for (let i = 0; i < length; i++) {
        let item = this.tipList.listData[i]
        if (item.productCode.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.barCode.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.proName.indexOf(inputvalue) == 0) {
          return i
        }
        // if (item.spec.indexOf(inputvalue) == 0) {
        //   return i
        // }
        if (item.company.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.warehouse.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.number.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.unitPrice.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.money.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.arrivalDate.indexOf(inputvalue) == 0) {
          return i
        }
        if (item.arrivalQty.indexOf(inputvalue) == 0) {
          return i
        }
        // if (item.unArrivalQty.indexOf(inputvalue) == 0) {
        //   return i
        // }
        // if (item.remarks.indexOf(inputvalue) == 0) {
        //   return i
        // }
      }
      return -1
    },
    // 找到输入框的值与提示框匹配的值
    findProduct(inputvalue, pipei_product) {
      var value = ''
      for (const key in pipei_product) {
        if (pipei_product[key].indexOf(inputvalue) == 0) {
          this.value = pipei_product[key]
          break
        }
      }
      return this.value
    },

    // 获取提示框当前选择的行数据
    activeMark(index) {
      this.tipList.mark = index
      this.selectListData = this.tipList.listData[index]
    },
    // 替换展示提示框当前选择的行数据
    selectMark() {
      this.tipList.displaySta = 'none' // 隐藏提示框
      // 替换当前选中数据
      for (const key in this.TableConfig.tableData[this.myRowIndex]) {
        this.TableConfig.tableData[this.myRowIndex][key] = this.selectListData[key]
      }
    },
    // 处理表格中重复的数据并返回一个新数组用来展示在提示框内
    handleTableData() {
      let arr = []
      for (let i = 0; i < this.TableConfig.tableData.length; i++) {
        if (JSON.stringify(arr).indexOf(this.TableConfig.tableData[i].productCode) == -1) {
          arr.push(this.TableConfig.tableData[i])
        }
      }
      let str = JSON.stringify(arr)
      let par = JSON.parse(str)
      this.tipList.listData = par
    },
    // 添加一行数据
    addRow(event, index, rows) {
      for (let i = 0; i < rows.length; i++) {
        if (index === i) {
          let arr = {
            productCode: '',
            barCode: '',
            proName: '',
            spec: '',
            company: '',
            warehouse: '',
            number: 0,
            unitPrice: '',
            money: 0,
            arrivalDate: '',
            arrivalQty: 0,
            unArrivalQty: 0,
            remarks: '',
          }
          rows.splice(i + 1, 0, arr)
        }
      }
      this.TableConfig.tableData = rows
      let trDown = event.target.parentNode.parentNode.parentNode.parentNode.nextElementSibling // 当前选中的下一行
      // setTimeout(() => {
      this.findinput(trDown.children[1]).select()
      // }, 300)
      this.$emit('onAddRow', this.TableConfig.tableData)
    },
    // 删除当前行数据
    deleteRow(index, rows) {
      rows.splice(index, 1)
      this.TableConfig.tableData = rows
      this.$emit('onDeleteRow', this.TableConfig.tableData)
    },
  },
}
</script>

<style lang="scss" scoped>
.table_div {
  width: 100%;
  // height: 100%;
  box-sizing: border-box;
  position: relative;
  border: 0.018751rem solid #000;
  overflow: auto;
  &::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  &::-webkit-scrollbar-thumb {
    background: #c9c9c9;
  }
  &::-webkit-scrollbar-track {
    background: #e5e5e5;
  }
}
.table_style {
  width: 100%;
  box-sizing: border-box;
  border-spacing: 0;
  // overflow: scroll;
  border: 1px solid #e3e3e3;
}
.table_style tr {
  position: relative;
  background: #fff;
}
.first_td {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 !important;
}
.first_td_p {
  width: 0.937559rem;
  height: 100%;
  line-height: 0.562535rem;
  font-size: 0.225014rem;
  color: #666;
  text-align: center;
}
.first_td_button {
  width: 100% !important;
  display: flex;
  justify-content: center;
}
.first_td_button p {
  width: 0.337521rem;
  height: 0.337521rem;
  border-radius: 50%;
  border: 0.037502rem solid #1893fc;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #1893fc;
  font-size: 0.337521rem;
  cursor: pointer;
  margin: 0;
}
.first_td_button p:first-child {
  margin-right: 0.037502rem;
}
.first_td_button p:last-child {
  margin-left: 0.037502rem;
  border-color: #fb1919;
  color: #fb1919;
}
.first_td_button p:last-child span {
  margin-top: -0.056254rem;
}
.table_style .tr_th {
  height: 0.562535rem;
  background: #ededed;
  box-sizing: border-box;
  th {
    border-right: 0.018751rem solid #e3e3e3;
    p {
      margin: 0;
      color: #666;
      font-size: 0.225014rem;
    }
  }
  :last-child {
    border-right: none;
  }
}
.table_style tr > td {
  border-top: 0.018751rem solid #e3e3e3;
  border-right: 0.018751rem solid #e3e3e3;
  padding: 0 0.093756rem;
  height: 0.562535rem;
  box-sizing: border-box;
  input {
    border: 0.018751rem solid #e3e3e3;
    height: 0.450028rem;
    width: 1.875117rem;
    padding: 0 0.093756rem;
    box-sizing: border-box;
    color: #666;
    font-size: 0.225014rem;
  }
}
.table_style tr > td:last-child {
  border-right: none;
}
.table_style tr > td > input:focus {
  outline: none;
  border: 0.018751rem solid #1893fc;
}

.table_style .last_tr {
  background: #ededed;
  td {
    box-sizing: border-box;
    padding: 0 0.187512rem;
    border-right: none;
    p {
      width: 100%;
      font-size: 0.225014rem;
      color: #666;
      margin: 0;
    }
  }
  td:first-child {
    text-align: center;
  }
}
.star {
  color: #fb1919;
  margin-right: 0.056254rem;
}

.tip_box {
  display: none;
  width: 8.625539rem;
  height: 3.000188rem;
  padding: .093756rem 0;
  overflow: auto;
  position: absolute;
  background: #fff;
  border: 1px solid #dcdfe6;
  box-shadow: 0rem 0rem 0.187512rem 0.018751rem rgba(0, 0, 0, 0.1);
  z-index: 999;
  transition: all 0.3s;
  &::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  &::-webkit-scrollbar-thumb {
    background: #c9c9c9;
  }
  &::-webkit-scrollbar-track {
    background: #e5e5e5;
  }
}
.tip_box td {
  padding: 0 .112507rem;
  height: .450028rem;
  white-space: nowrap;
  text-align: left;
  margin: 0;
  border: none;
  // border-spacing: 0;
  color: #666;
  font-size: 0.225014rem;
  cursor: pointer;
}
.active_backGround {
  background: #e3f6ff;
}
.tip_box .active_mark {
  background: #e3f6ff;
}
</style>